package com.xrkj.b2c.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * 
 * <B>系统名称：</B><BR>
 * <B>模块名称：</B><BR>
 * <B>中文类名：</B>文件工具类<BR>
 * <B>概要说明：</B><BR>
 * @author 赵子靖
 * @since 2018年07月15日
 */
public class FileUtil {
	/**
	 * 日志打印对象
	 */
	private static final Logger logger = Logger.getLogger(FileUtils.class);

	// 删除整个目录，包括子目录 方法
	public static void deleteFile(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {
			if (file.isDirectory()) {
				File[] filelist = file.listFiles();
				for (File subfile : filelist) {
					deleteFile(subfile.getAbsolutePath());
				}
			}
			file.delete();
		}
	}

	/**
	 * 自己写文件，一解决在linux中renameTo不能工作的问题
	 * 
	 * @param f
	 * @param newFile
	 * @throws IOException
	 */
	public static void writeTo(File f, File newFile) throws IOException {
		FileInputStream fis = new FileInputStream(f);
		FileOutputStream fos = new FileOutputStream(newFile);
		try {
			byte[] buf = new byte[8192];
			do {
				int rc = fis.read(buf);
				if (rc == -1)
					break;
				fos.write(buf, 0, rc);
			} while (true);
		} finally {
			fis.close();
			fos.close();
		}
	}

	// 复制文件
	public static boolean copyFile(File src, File dst) throws IOException {
		// if the parameters are same,then don't excute anything.or it make
		// original file null.
		if (!src.getAbsolutePath().equalsIgnoreCase(dst.getAbsolutePath())) {
			InputStream in = new FileInputStream(src);
			OutputStream out = new FileOutputStream(dst);
			// Transfer bytes from in to out
			byte[] buf = new byte[1024 * 5];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			// out.flush();
			in.close();
			out.close();
		}
		return true;
	}

	// 上传文件
	public static boolean upFile(InputStream in, String TargetPath)
			throws FileNotFoundException, IOException {
		// if the parameters are same,then don't excute anything.or it make
		// original file null.
		File targetfile = new File(TargetPath);

		if (!targetfile.exists())
			makeFile(TargetPath);
		OutputStream out = new FileOutputStream(TargetPath);
		try {
			System.out.println("=upFile begin transfer file=");
			// Transfer bytes from in to out
			byte[] buf = new byte[1024 * 5];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
		} catch (FileNotFoundException e) {
			// TODO 自动生成 catch 块
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			// TODO 自动生成 catch 块
			e.printStackTrace();
			throw e;
		} finally {
			in.close();
			out.close();
		}

		return true;
	}

	// 删除文件
	public static boolean delFileByName(String file) throws Exception {
		File f = new File(file);

		// File fB = new File(file1);
		if (f.exists()) {
			logger.info("begin delete the file==>" + file
					+ "  from the file system!");
			f.delete();
		} else {
			logger.info(file + "not in the file system!");
		}

		return true;
	}

	/**
	 * 创建目录 不存在时创建。已存在目录时，直接返回。
	 * 
	 * @param folderPath
	 *            :目录路径
	 * @return
	 * @throws IOException
	 */
	public static boolean createFolder(String folderPath) throws IOException {
		boolean result = false;
		File f = new File(folderPath);
		if (!f.isDirectory())
			result = f.mkdirs();
		return result;
	}

	/**
	 * 删除目录下所有文件
	 * 
	 * @param directory
	 *            (File 对象)
	 */
	public static boolean emptyDirectory(File directory) {
		File[] entries = directory.listFiles();
		for (int i = 0; i < entries.length; i++) {
			entries[i].delete();
		}
		return true;
	}

	/**
	 * 创建文件
	 * 
	 * @param filepath
	 *            :文件所在目录路径,比如:c:/test/test.txt test目录必须存在。
	 * @return
	 */
	public static boolean makeFile(String filepath) throws IOException {
		boolean result = false;
		File file = new File(filepath);

		result = file.createNewFile();

		file = null;
		return result;
	}

	/**
	 * 删除文件
	 * 
	 * @param filepath
	 *            :文件所在物理路径
	 * @return
	 */
	public static boolean isDel(String filepath) {
		boolean result = false;
		File file = new File(filepath);
		result = file.delete();
		file = null;
		return result;
	}

	/**
	 * 文件重命名
	 * 
	 * @param filepath
	 *            :文件所在物理路径
	 * @param destname
	 *            :新文件名
	 * @return
	 */
	public static boolean renamefile(String filepath, String destname) {
		boolean result = false;
		File f = new File(filepath);
		String fileParent = f.getParent();
		File rf = new File(fileParent + File.separator + destname);
		if (f.renameTo(rf)) {
			result = true;
		}
		f = null;
		rf = null;
		return result;
	}

	/**
	 * 将文件内容写入文件中
	 * 
	 * @param filepath
	 *            :文件所在物理路径
	 * @param content
	 *            :写入内容
	 * @throws Exception
	 */
	public static boolean WriteFile(String filepath, String content)
			throws Exception {
		FileWriter filewriter = new FileWriter(filepath, true); // 写入多行
																// 第2个参数=true
																// append的方式写入
		PrintWriter printwriter = new PrintWriter(filewriter);
		printwriter.println(content);
		printwriter.flush();
		printwriter.close();
		filewriter.close();
		return true;
	}

	/**
	 * 将文件内容写入文件中
	 * 
	 * @param filepath
	 *            :文件所在物理路径
	 * @param content
	 *            :写入内容
	 * @param charset
	 *            :字符集
	 * @throws Exception
	 */
	public static boolean writeFile(String filepath, String content,
			String charset) throws Exception {
		final Writer out = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(filepath), charset));
		out.write(content);
		out.close();
		return true;
	}

	/**
	 * 将文件内容写入到WebRoot下的指定目录的文件中
	 * 
	 * @param filePath
	 *            ----> 文件所在物理路径
	 * @param content
	 *            ----> 写入的内容
	 * @param charset
	 *            ----> 字符集
	 * @param isRoot
	 *            ----> 是否以根路径做为目录开头
	 * @return boolean
	 * @throws Exception
	 */
//	public static boolean writeFile(String filePath, String content,
//			String charset, boolean isRoot) throws Exception {
//
//		final String rootPath = isRoot ? WebUtils.getRoot() : "";
//		final int index = filePath.lastIndexOf("/");
//		final String folderPath = rootPath + filePath.substring(0, index);
//		FileUtil.createFolder(folderPath);
//
//		final Writer out = new BufferedWriter(new OutputStreamWriter(
//				new FileOutputStream(rootPath + filePath), charset));
//		out.write(content);
//		out.close();
//		return true;
//	}

	/**
	 * 该方法用于从WebRoot目录下读取文件内容
	 * 
	 * @param filePath
	 *            ----> 文件所在物理路径
	 * @param charset
	 *            ----> 字符集
	 * @param isRoot
	 *            ----> 是否以根路径做为目录开头
	 * @return String ----> 返回文件内容
	 * @throws Exception
	 */
//	public static String readFile(String filePath, String charset,
//			boolean isRoot) throws Exception {
//
//		String content = "";
//		final String rootPath = isRoot ? WebUtils.getRoot() : "";
//		final File file = new File(rootPath + filePath);
//		if (file.exists()) {
//			content = FileUtils.readFileToString(file, charset);
//		}
//		return content;
//	}

	/**
	 * 日志备份
	 * 
	 * @param filePath
	 *            :日志备份路径
	 * @param baksize
	 *            :日志备份大小参考值(字节大小)
	 * @throws IOException
	 */
	public static boolean logBak(String filePath, long baksize)
			throws IOException {
		File f = new File(filePath);
		long len = f.length();
		SimpleDateFormat simpledateformat = new SimpleDateFormat(
				"yyyyMMddHHmmss");
		String s = simpledateformat.format(new Date());
		String fileName = f.getName();
		int dot = fileName.indexOf(".");
		String bakName = s + fileName.substring(dot);
		System.out.println(bakName);
		if (len >= baksize) {
			renamefile(filePath, bakName);
			makeFile(filePath);
		}
		f = null;
		return true;
	}
	
	/*======================================================== 文件工具类 2013-11-11 ================================================================*/
	
	/**
	 * 读取文件内容
	 * 
	 * @param path
	 *            ----> 文件路径
	 * @param encoding
	 *            ----> 文件编码
	 * @return 返回文件内容
	 * @throws Exception
	 */
	public static String readFile(String path, String... encoding)
			throws Exception {

		String fileContent = new String();
		final File file = new File(path);
		if (file.exists()) {
			fileContent = (null != encoding && encoding.length > 0) ? FileUtils
					.readFileToString(file, encoding[0]) : FileUtils
					.readFileToString(file);
		}
		return fileContent;
	}

	/**
	 * 向文件中写入内容
	 * 
	 * @param path
	 *            ----> 文件路径
	 * @param content
	 *            ----> 内容
	 * @param encoding
	 *            ----> 文件编码
	 * @return 返回文件内容
	 * @throws Exception
	 */
	public static void writeFile(String path, String content,
			String... encoding) throws Exception {

		if (StringUtils.isNotBlank(content)) {
			if (null != encoding && encoding.length > 0) {
				FileUtils.writeStringToFile(new File(path), content,
						encoding[0]);
			} else {
				FileUtils.writeStringToFile(new File(path), content);
			}
		}
	}

	/**
	 * 获取文件名称（不含后缀名）
	 * 
	 * @param file
	 * @return String
	 */
	public static String getFileNameWithoutSuffix(File file) {

		String fileName = null;
		if (file != null && file.exists() && file.isFile()) {
			String name = file.getName();
			int index = name.lastIndexOf(".");
			if (index != -1)
				fileName = name.substring(0, index);
		}
		return fileName;
	}

	/**
	 * 复制文件夹
	 * 
	 * @param srcDirPath
	 * @param destDirPath
	 */
	public static void copyDirectory(String srcDirPath, String destDirPath) {

		final File srcDir = new File(srcDirPath);
		final File destDir = new File(destDirPath);
		try {
			FileUtils.copyDirectory(srcDir, destDir);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 删除文件夹
	 * 
	 * @param srcDirPath
	 * @param destDirPath
	 */
	public static void deleteDirectory(String srcDirPath) {

		final File srcDir = new File(srcDirPath);
		try {
			FileUtils.deleteDirectory(srcDir);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 移动文件夹
	 * 
	 * @param srcDirPath
	 * @param destDirPath
	 */
	public static void moveDirectory(String srcDirPath, String destDirPath) {

		copyDirectory(srcDirPath, destDirPath);
		deleteDirectory(srcDirPath);
	}

	/**
	 * 获取目录下的所有文件
	 * 
	 * @param dirPath
	 *            ----> 目录路径
	 * @param filter
	 *            ----> 文件过滤条件
	 * @return File集合
	 */
	public static List<File> getFilesOfDirectory(String dirPath,
			String... filter) {

		final List<File> fileList = new ArrayList<File>();
		final File dir = new File(dirPath);
		if (dir.exists() && dir.isDirectory()) {
			final Iterator<File> it = FileUtils.iterateFiles(dir,
					filter != null && filter.length > 0 ? filter : null, false);
			for (; it.hasNext();) {
				fileList.add(it.next());
			}
		}
		return sortedListByName(fileList);
	}
	
	/**
	 * 按文件名称自然排序
	 * 
	 * @param fileList ----> 需要排序的File集合
	 * 
	 * @return File集合
	 */
	public static List<File> sortedListByName(List<File> fileList) {
		
		Collections.sort(fileList, new Comparator<File>() {

			@Override
			public int compare(File file1, File file2) {
				final String f1_name = file1.getName();
				final String f2_name = file2.getName();
				
				if (null == f1_name || null == f2_name) {
					throw new NullPointerException("The strings must not be null");
				}
				
				return f1_name.compareTo(f2_name);
			}
		});
		return fileList;
	}
}
